from src.video.baseInfo.VideoFolderInfo import VideoFolderInfo
from src.video.baseInfo.VideoHeapsInfo import HeapInfo
from src.utils.file_utils import read_file
from src.utils.srt_utils import get_srt_texts,get_srt_text_from_time
from src.utils.text_utils import remove_non_chinese, remove_non_english_chars
from moviepy.editor import *
from moviepy.Clip import Clip
from typing import List
import random
import pysrt


class VideoCompositorNosrt():
    def __init__(self, video_folder_info: VideoFolderInfo, video_heap_list: List[HeapInfo], pic_num_per_second: int
                 , save_temp_result=False
                 , grap_second=6):
        self.videoFolderInfo = video_folder_info
        self.videoHeapList = video_heap_list
        self.picNumPerSecond = pic_num_per_second
        self.saveTempResult = save_temp_result
        self.grap_second = grap_second

    def _cut_movie_into_pieces(self,info_dict) -> List[Clip]:
        movie = VideoFileClip(self.videoFolderInfo.origin_mp4_file)

        subMovies = []
        currentSecond = 0

        origin_srt_time_list = get_srt_texts(self.videoFolderInfo.origin_srt_file)


        video_parts = []
        for index, info in enumerate(info_dict):
            expect_second = len(info.heap_index)   /3
            add_x = 0#int(4*expect_second) /2
            start  = (info.max_relative_heap_inner_index - add_x) / (self.picNumPerSecond + 1)
            end = start + expect_second
            if index == 0:
                expect_second -= 1
            find_result = get_srt_text_from_time(origin_srt_time_list,start,end,expect_second)
            if find_result:
                video_start = find_result['start']
                offset_time = find_result['duration']
            else:
                offset_time = expect_second + 0.2
                video_start = start - 0.1 - (expect_second -end + start)/2

            video_parts.append([video_start,video_start + offset_time])

        final_parts = self.merge_combine_second(video_parts)

        for index, info in enumerate(final_parts):
            if currentSecond == 0:
                subVideo = movie.subclip(info[0], info[1])
            else:
                subVideo = movie.subclip(info[0], info[1] + 0.5)

            # random_int = random.choice(randomList)
            # if random_int == 1:
            #     subVideo = subVideo.fx(vfx.mirror_x)
            if self.saveTempResult:
                save_path = os.path.join(self.videoFolderInfo.jieshuoHeapSaveFolder, str(index) + ".mp4")
                subVideo.write_videofile(save_path)
            if currentSecond == 0:
                subMovies.append(subVideo)
            else:
                subMovies.append(subVideo.set_start(currentSecond).crossfadein(0.5))
            currentSecond += info[1] - info[0]
            print(currentSecond)
        return subMovies

    def check_node_relative(self, before_node, after_node):
        '''
        判断两个视频片段是否相邻
        :param before_node:
        :param after_node:
        :return:
        '''
        if min(after_node.max_relative_heap_index) - max(before_node.max_relative_heap_index) <= self.grap_second and \
                min(after_node.max_relative_heap_index) - max(before_node.max_relative_heap_index) > 0:
            return True
        else:
            return False

    def check_node_greate_than_other(self, before_node, after_node):
        if min(before_node.max_relative_heap_index) - max(after_node.max_relative_heap_index) > 0:
            return True
        else:
            return False

    def resort_time_list(self):
        '''

        :param heap_seconds:
        :param saveFileName:
        :return:
        '''
        current_index = 0

        final_nodes = []
        before_node = self.videoHeapList[current_index]
        final_nodes.append(before_node)
        while current_index < len(self.videoHeapList) - 1:
            if before_node == None:
                before_node = self.videoHeapList[current_index]

            next_node = self.videoHeapList[current_index + 1]
            if self.check_node_relative(before_node, next_node):
                final_nodes.append(next_node)
                before_node = next_node
                current_index += 1
            else:
                if current_index + 2 < len(self.videoHeapList):
                    next_node_next = self.videoHeapList[current_index + 2]
                    if self.check_node_relative(before_node, next_node_next):
                        final_nodes.append(next_node_next)
                        before_node = next_node_next
                        current_index += 2
                    elif self.check_node_relative(next_node, next_node_next):
                        final_nodes.append(next_node)
                        final_nodes.append(next_node_next)
                        before_node = next_node_next
                        current_index += 2
                    else:
                        if len(next_node.max_relative_heap_index) >= 10:
                            final_nodes.append(next_node)
                            current_index += 1
                            before_node = next_node
                        else:
                            before_node = next_node_next
                            current_index += 2
                else:
                    final_nodes.append(next_node)
                    before_node = next_node
                    current_index += 1

        self.videoHeapList = final_nodes

    def merge_relative_heap(self):
        current_index = 0

        final_nodes = []
        before_node = self.videoHeapList[current_index]
        temp = [before_node]
        while current_index < len(self.videoHeapList) - 1:
            next_node = self.videoHeapList[current_index + 1]
            if not self.check_node_relative(before_node, next_node):
                if len(temp) == 1:
                    if len(temp[0].max_relative_heap_index) <= 12:
                        temp = []
                if temp:
                    for i in temp:
                        final_nodes.append(i)
                    temp = []

            temp.append(next_node)
            before_node = next_node
            current_index += 1

        if temp:
            for i in temp:
                final_nodes.append(i)
        return final_nodes

    def merge_combine_second(self,video_parts):

        def have_intersection(intervalA, intervalB):
            x1, y1 = intervalA
            x2, y2 = intervalB
            return max(x1, x2) <= min(y1, y2)
        first = video_parts[0]
        after  = video_parts[1:]
        after.sort(key= lambda x:x[0])

        temp_start = first[0]
        temp_end = first[1]
        final = []
        for index, item in enumerate(after):
            if have_intersection((temp_start,temp_end),item):
                temp_start = min(temp_start,item[0])
                temp_end = max(temp_end,item[1])
                if index == len(after) -1:
                    final.append((temp_start,temp_end))
            else:
                final.append([temp_start,temp_end])
                temp_start = item[0]
                temp_end = item[1]
                if index == len(after) - 1:
                    final.append((temp_start, temp_end))
        return final





    def merge_pieces_into_video(self, sub_movies: List[Clip], save_name):
        # finalclip = CompositeVideoClip(sub_movies)

        with CompositeVideoClip(sub_movies) as video:
            video.write_videofile(save_name, threads=32)

    def process(self):
        if not os.path.exists(self.videoFolderInfo.finalVideoName):
            self.resort_time_list()
            final_list = self.merge_relative_heap()
            subMovies = self._cut_movie_into_pieces(final_list)
            self.merge_pieces_into_video(subMovies,self.videoFolderInfo.finalVideoName)